/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

	PrintSample

		DocumentFunctions.cpp

			Functions used to create and destroy the example document
			content.

			The document content used in this example is just the 
			information content of a document that is stored in 
			a data structure as might be done in a document-based 
			application. The document structure is a nested set of
			data structures:

				A document structure
							that contains an array of
					Page structures
							that each contain an array of
						Text element structures

			This organization can be modified to accomodate your
			particular application.

 ------------------------------------------------------------------

 Copyright (c) 2010 Microsoft Corporation. All rights reserved.

 THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
 ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 
 PARTICULAR PURPOSE.

 ------------------------------------------------------------------
*/
#include "stdafx.h"
#include "PrintSample.h"

// Document parameters used in this example
// XPS documents use XPS units of measure.
// There are 96 XPS units per inch.
//
// width = 8.5" * 96 units per inch
#define PRINTSAMPLE_PAGE_WIDTH		816
// height = 11.0" * 96 units per inch
#define PRINTSAMPLE_PAGE_HEIGHT		1056
// each page has three text items
//	1)
//  2)
//	3)
#define PRINTSAMPLE_TEXT_ITEMS_PER_PAGE	3
//
// Text item 1
#define	PRINTSAMPLE_TEXT_ITEM_1_X		50.0f
#define	PRINTSAMPLE_TEXT_ITEM_1_Y		200.0f
#define	PRINTSAMPLE_TEXT_ITEM_1_SIZE	72.0f
#define	PRINTSAMPLE_TEXT_ITEM_1_TEXT	L"XPS"
//
// Text item 2
#define	PRINTSAMPLE_TEXT_ITEM_2_X		420.0f
#define	PRINTSAMPLE_TEXT_ITEM_2_Y		300.0f
#define	PRINTSAMPLE_TEXT_ITEM_2_SIZE	36.0f
#define	PRINTSAMPLE_TEXT_ITEM_2_TEXT	L"Print with Confidence"
//
// Text item 3
#define	PRINTSAMPLE_TEXT_ITEM_3_X		420.0f
#define	PRINTSAMPLE_TEXT_ITEM_3_Y		200.0f
#define	PRINTSAMPLE_TEXT_ITEM_3_SIZE	36.0f
#define	PRINTSAMPLE_TEXT_ITEM_3_TEXT	L"Page: %d"


/** 
	<module>DocumentFunctions.cpp</module>

	<summary>
		Creates a new test document.</summary>

	<param name="threadInfo">
		The application-specific structure that describes the 
		current document and print job.</param>

	<param name="numPages">
		The integer number of pages to create in the new 
		document.</param>

	<returns>
		<p>HRESULT value that indicates the success or failure 
		of the procedure.</p>
		</returns>

	<remarks>
		<p>The document text is hard-coded for the sake of 
		simplicity in this example.</p>
		</remarks>

*/
HRESULT 
CreateTestDocumentContent (
		PPRINTTHREADINFO threadInfo, 
		DWORD numPages
)
{
	HRESULT hr = S_OK;

	// Creates a document that simulates the application's data 
	//  to be printed.
	// Normally, this content would be generated by the application;
	//  for example, the content of a document.
		
	PDOCUMENTCONTENT testDocument = NULL;
	
	// Allocate one DOCUMENTCONTENT structure
	testDocument = (PDOCUMENTCONTENT)HeapAlloc(
						GetProcessHeap(), 
						PRINT_SAMPLE_HEAP_FLAGS, 
						sizeof(DOCUMENTCONTENT));
	
	if (NULL != testDocument)
	{
		// Allocate an array of PAGECONTENT structures
		testDocument->pages = numPages;
		testDocument->pageContentArray = (PPAGECONTENT)HeapAlloc(
						GetProcessHeap(), 
						PRINT_SAMPLE_HEAP_FLAGS, 
						(testDocument->pages * sizeof(PAGECONTENT)));

		if (NULL != testDocument->pageContentArray)
		{
			// Create the content for each page.
			//  In this example, each page contains three (3) text 
			//	elements.
			DWORD p = 0;
			PPAGECONTENT pageContent = testDocument->pageContentArray;
			for (p = 0; p < testDocument->pages; p++)
			{
				pageContent[p].pageNumber = p+1;
				pageContent[p].pageSize.width = PRINTSAMPLE_PAGE_WIDTH;
				pageContent[p].pageSize.height = PRINTSAMPLE_PAGE_HEIGHT;
				pageContent[p].pageTextItems = PRINTSAMPLE_TEXT_ITEMS_PER_PAGE;
				// Allocate data for this page's text elements
				pageContent[p].pageTextArray = (PPAGETEXT)HeapAlloc(
						GetProcessHeap(), 
						PRINT_SAMPLE_HEAP_FLAGS, 
						(pageContent[p].pageTextItems * sizeof(PAGETEXT)));

				if (NULL != pageContent[p].pageTextArray)
				{
					DWORD	t = 0;
					PPAGETEXT	pageText = pageContent[p].pageTextArray;

				    if (SUCCEEDED(hr))
					{
						// Create first text entry for the page
						pageText[t].textOrigin.x = PRINTSAMPLE_TEXT_ITEM_1_X;
						pageText[t].textOrigin.y = PRINTSAMPLE_TEXT_ITEM_1_Y;
						pageText[t].fontSize = PRINTSAMPLE_TEXT_ITEM_1_SIZE;
						pageText[t].textStyle = XPS_STYLE_SIMULATION_NONE;
						if (swprintf_s (
							pageText[t].text,
							MAXIMUM_TEXT_FIELD_LENGTH,
							PRINTSAMPLE_TEXT_ITEM_1_TEXT) < 0)
						{
							// Error writing string to text structure
							hr = E_FAIL;
						}
					}

				    if (SUCCEEDED(hr))
					{
						// Increment entry index
						t++; 
						// Create the next text entry for this page
						pageText[t].textOrigin.x = PRINTSAMPLE_TEXT_ITEM_2_X;
						pageText[t].textOrigin.y = PRINTSAMPLE_TEXT_ITEM_2_Y;
						pageText[t].fontSize = PRINTSAMPLE_TEXT_ITEM_2_SIZE;
						pageText[t].textStyle = XPS_STYLE_SIMULATION_ITALIC;
						if (swprintf_s (
							pageText[t].text,
							MAXIMUM_TEXT_FIELD_LENGTH,
							PRINTSAMPLE_TEXT_ITEM_2_TEXT) < 0)
						{
							// Error writing string to text structure
							hr = E_FAIL;
						}
					}

				    if (SUCCEEDED(hr))
					{
						// Increment entry index
						t++; 
						// Create the next text entry for this page
						pageText[t].textOrigin.x = PRINTSAMPLE_TEXT_ITEM_3_X;
						pageText[t].textOrigin.y = PRINTSAMPLE_TEXT_ITEM_3_Y;
						pageText[t].fontSize = PRINTSAMPLE_TEXT_ITEM_3_SIZE;
						pageText[t].textStyle = XPS_STYLE_SIMULATION_NONE;
						if (swprintf_s (
							pageText[t].text,
							MAXIMUM_TEXT_FIELD_LENGTH,
							PRINTSAMPLE_TEXT_ITEM_3_TEXT,
							(p+1)) < 0)
						{
							// Error writing string to text structure
							hr = E_FAIL;
						}
					}
				}
				else
				{
					// Unable to allocate page text array
					hr = E_OUTOFMEMORY;
				}
			}
		    if (SUCCEEDED(hr))
			{
				// Document created and ready
				//  so add to the application's main data structure
				threadInfo->documentContent = testDocument;
			}
		}
		else
		{
			// Unable to allocate page content array
			hr = E_OUTOFMEMORY;
		}
	}
	else
	{
		// Unable to allocate test document structure
		hr = E_OUTOFMEMORY;
	}

	return hr;
}

/** 
	<module>DocumentFunctions.cpp</module>

	<summary>
		Deletes a test document and frees the resources associated 
		with it.</summary>

	<param name="threadInfo">
		The application-specific structure that describes the current
		document and print job.</param>

	<returns>
		<p>HRESULT value that indicates the success or failure of 
		the procedure.</p>
		</returns>

*/
HRESULT 
DeleteDocumentContent (
		PPRINTTHREADINFO threadInfo
)
{
	HRESULT hr = S_OK;
	PDOCUMENTCONTENT testDocument;
	
	if (NULL != threadInfo)
	{
		testDocument = threadInfo->documentContent;

		if (NULL != testDocument)
		{
			if (NULL != testDocument->pageContentArray)
			{
				// Free page content
				DWORD	p = 0;
				PPAGECONTENT	pageContent = testDocument->pageContentArray;
				for (p = 0; p < testDocument->pages; p++)
				{
					// Free page text
					if (NULL != pageContent[p].pageTextArray)
					{
						HeapFree (
							GetProcessHeap(), 
							0L, 
							pageContent[p].pageTextArray);
						pageContent[p].pageTextArray = NULL;
					}
				}
				HeapFree (
					GetProcessHeap(), 
					0L, 
					testDocument->pageContentArray);
				testDocument->pageContentArray = NULL;
			}
			HeapFree (GetProcessHeap(), 0L, threadInfo->documentContent);
			threadInfo->documentContent = NULL;
		}
	}
	else
	{
		// Structure already released
	}
	return hr;
}